package com.example.lock.redisLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisException;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

public class BaseJedisClusterLock {
    private static Logger logger = LoggerFactory.getLogger(BaseJedisLock.class);

    public static JedisCluster jedisCluster;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(300);
        config.setMaxTotal(60000);
        config.setTestOnBorrow(true);
        Set<HostAndPort> nodes = new HashSet<HostAndPort>();
        nodes.add(new HostAndPort("127.0.0.1", 7000));
        nodes.add(new HostAndPort("127.0.0.1", 7001));
        nodes.add(new HostAndPort("127.0.0.1", 7002));
        nodes.add(new HostAndPort("127.0.0.1", 7003));
        nodes.add(new HostAndPort("127.0.0.1", 7004));
        nodes.add(new HostAndPort("127.0.0.1", 7005));
        jedisCluster = new JedisCluster(nodes,config);
    }


    /**
     * 加锁
     * @param lockName  锁的key
     * @param acquireTimeout  获取超时时间
     * @param timeout   锁的超时时间
     * @return 锁标识
     */
    public static String lockWithTimeout(String lockName,
                                         long acquireTimeout, long timeout) {

        String retIdentifier = null;
        try {
            // 释放锁的标识
            String identifier = UUID.randomUUID().toString();
            // 锁名，即key值
            String lockKey = "Lock:" + lockName;
            // 超时时间，上锁后超过此时间则自动释放锁
            int lockExpire = (int)(timeout / 1000);

            // 获取锁的超时时间，超过这个时间则放弃获取锁
            long end = System.currentTimeMillis() + acquireTimeout;
            while (System.currentTimeMillis() < end) {
                if (jedisCluster.setnx(lockKey, identifier) == 1) {
                    jedisCluster.expire(lockKey, lockExpire);
                    // 返回value值，用于释放锁时间确认
                    retIdentifier = identifier;
                    return retIdentifier;
                }
                // 返回-1代表key没有设置超时时间，为key设置一个超时时间
                if (jedisCluster.ttl(lockKey) == -1) {
                    jedisCluster.expire(lockKey, lockExpire);
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (JedisException e) {
            e.printStackTrace();
        }
        return retIdentifier;
    }


    /**
     * 释放锁
     * @param lockName 锁的key
     * @param identifier    释放锁的标识
     * @return
     */
    public static boolean releaseLock(String lockName, String identifier) {
        String lockKey = "Lock:" + lockName;
        boolean retFlag = false;
        try {
                // 通过前面返回的value值判断是不是该锁，若是该锁，则删除，释放锁
                if (identifier.equals(jedisCluster.get(lockKey))) {
                    Long del = jedisCluster.del(lockKey);
                    System.out.println("返回"+del);
                    logger.info("返回值{}",del);
            }
        } catch (JedisException e) {
            e.printStackTrace();
        }
        return retFlag;
    }


    public static void main(String[] args) {
        BaseJedisClusterLock.jedisCluster.set("test","test");
        BaseJedisClusterLock.jedisCluster.set("test1","test1");
    }
}
